/*****************************************************
 * jr generated file
 ****************************************************/
import edu.ucdavis.jr.*;
import edu.ucdavis.jr.jrx.*;
import java.rmi.*;
import java.io.Serializable;


import edu.ucdavis.jr.*;
import java.util.*;

public class PlainDiffusion extends java.lang.Object {
    { JRinit(); }
    
    public PlainDiffusion() {
        super();
        JRprocess();
    }
    public static final String DBG = "PlainDiffusion";
    public static boolean debug = true;
    public static String network = "spantree";
    public static boolean warmup = false;
    public static int cycleLimit = 0;
    static DiffusionCountProcessor[] processors = new DiffusionCountProcessor[]{new DiffusionCountProcessor(0), new DiffusionCountProcessor(1), new DiffusionCountProcessor(2), new DiffusionCountProcessor(3), new DiffusionCountProcessor(4), new DiffusionCountProcessor(5), new DiffusionCountProcessor(6)};
    
    public static void main(String[] args) {
        String dbgPfx = DBG + "#main():";
        JRLoop10: for (int i = 0; i < args.length; i++) {
            if (args[i].startsWith("-d")) {
                debug = Boolean.valueOf(args[i].substring(2));
                DebugUtil.out(dbgPfx + "got debug (" + debug + ")", true);
            } else if (args[i].startsWith("-n")) {
                network = args[i].substring(2);
                DebugUtil.out(dbgPfx + "got network (" + network + ")", true);
            } else if (args[i].startsWith("-c")) {
                cycleLimit = Integer.parseInt(args[i].substring(2));
                DebugUtil.out(dbgPfx + "got cycle limit (" + cycleLimit + ")", true);
            }
        }
        if (network.startsWith("span")) {
            setupSpanNetworkTest();
        } else if (network.startsWith("ring")) {
            setupRingNetworkTest();
        } else if (network.startsWith("mesh")) {
            setupMeshNetworkTest();
        } else {
        }
        try {
            warmup = false;
            processors[0].setEstimate(1);
            boolean cycling = true;
            JRLoop12: while (cycling) {
                cycling = false;
                JRLoop11: for (int p = 0; p < processors.length; p++) {
                    if (processors[p].cycle < cycleLimit) {
                        cycling = true;
                        break JRLoop11;
                    }
                }
                Thread.sleep(1000);
            }
            JRget_op_report_voidTovoid().call(jrvm.getTimestamp());
            System.exit(0);
        } catch (java.lang.InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void setupSpanNetworkTest() {
        ArrayList nbs0 = new ArrayList();
        ArrayList nbs1 = new ArrayList();
        ArrayList nbs2 = new ArrayList();
        ArrayList nbs3 = new ArrayList();
        ArrayList nbs4 = new ArrayList();
        ArrayList nbs5 = new ArrayList();
        ArrayList nbs6 = new ArrayList();
        nbs0.add(((DiffusionCountProcessor)processors[1]));
        nbs1.add(((DiffusionCountProcessor)processors[0]));
        nbs1.add(((DiffusionCountProcessor)processors[2]));
        nbs1.add(((DiffusionCountProcessor)processors[3]));
        nbs2.add(((DiffusionCountProcessor)processors[1]));
        nbs2.add(((DiffusionCountProcessor)processors[4]));
        nbs2.add(((DiffusionCountProcessor)processors[5]));
        nbs2.add(((DiffusionCountProcessor)processors[6]));
        nbs3.add(((DiffusionCountProcessor)processors[1]));
        nbs4.add(((DiffusionCountProcessor)processors[2]));
        nbs5.add(((DiffusionCountProcessor)processors[2]));
        nbs6.add(((DiffusionCountProcessor)processors[2]));
        warmup = true;
        processors[0].setNeighbors(nbs0);
        processors[1].setNeighbors(nbs1);
        processors[2].setNeighbors(nbs2);
        processors[3].setNeighbors(nbs3);
        processors[4].setNeighbors(nbs4);
        processors[5].setNeighbors(nbs5);
        processors[6].setNeighbors(nbs6);
        processors[0].setCycleLimit(cycleLimit);
        processors[1].setCycleLimit(cycleLimit);
        processors[2].setCycleLimit(cycleLimit);
        processors[3].setCycleLimit(cycleLimit);
        processors[4].setCycleLimit(cycleLimit);
        processors[5].setCycleLimit(cycleLimit);
        processors[6].setCycleLimit(cycleLimit);
    }
    
    public static void setupRingNetworkTest() {
        ArrayList nbs0 = new ArrayList();
        ArrayList nbs1 = new ArrayList();
        ArrayList nbs2 = new ArrayList();
        ArrayList nbs3 = new ArrayList();
        ArrayList nbs4 = new ArrayList();
        ArrayList nbs5 = new ArrayList();
        ArrayList nbs6 = new ArrayList();
        nbs0.add(((DiffusionCountProcessor)processors[1]));
        nbs0.add(((DiffusionCountProcessor)processors[2]));
        nbs1.add(((DiffusionCountProcessor)processors[0]));
        nbs1.add(((DiffusionCountProcessor)processors[4]));
        nbs2.add(((DiffusionCountProcessor)processors[0]));
        nbs2.add(((DiffusionCountProcessor)processors[3]));
        nbs3.add(((DiffusionCountProcessor)processors[2]));
        nbs3.add(((DiffusionCountProcessor)processors[6]));
        nbs4.add(((DiffusionCountProcessor)processors[1]));
        nbs4.add(((DiffusionCountProcessor)processors[5]));
        nbs5.add(((DiffusionCountProcessor)processors[4]));
        nbs5.add(((DiffusionCountProcessor)processors[6]));
        nbs6.add(((DiffusionCountProcessor)processors[3]));
        nbs6.add(((DiffusionCountProcessor)processors[5]));
        warmup = true;
        processors[0].setNeighbors(nbs0);
        processors[1].setNeighbors(nbs1);
        processors[2].setNeighbors(nbs2);
        processors[3].setNeighbors(nbs3);
        processors[4].setNeighbors(nbs4);
        processors[5].setNeighbors(nbs5);
        processors[6].setNeighbors(nbs6);
        processors[0].setCycleLimit(cycleLimit);
        processors[1].setCycleLimit(cycleLimit);
        processors[2].setCycleLimit(cycleLimit);
        processors[3].setCycleLimit(cycleLimit);
        processors[4].setCycleLimit(cycleLimit);
        processors[5].setCycleLimit(cycleLimit);
        processors[6].setCycleLimit(cycleLimit);
    }
    
    public static void setupMeshNetworkTest() {
        ArrayList nbs0 = new ArrayList();
        ArrayList nbs1 = new ArrayList();
        ArrayList nbs2 = new ArrayList();
        ArrayList nbs3 = new ArrayList();
        ArrayList nbs4 = new ArrayList();
        ArrayList nbs5 = new ArrayList();
        ArrayList nbs6 = new ArrayList();
        nbs0.add(((DiffusionCountProcessor)processors[1]));
        nbs0.add(((DiffusionCountProcessor)processors[2]));
        nbs0.add(((DiffusionCountProcessor)processors[3]));
        nbs0.add(((DiffusionCountProcessor)processors[4]));
        nbs0.add(((DiffusionCountProcessor)processors[5]));
        nbs0.add(((DiffusionCountProcessor)processors[6]));
        nbs1.add(((DiffusionCountProcessor)processors[0]));
        nbs1.add(((DiffusionCountProcessor)processors[2]));
        nbs1.add(((DiffusionCountProcessor)processors[3]));
        nbs1.add(((DiffusionCountProcessor)processors[4]));
        nbs1.add(((DiffusionCountProcessor)processors[5]));
        nbs1.add(((DiffusionCountProcessor)processors[6]));
        nbs2.add(((DiffusionCountProcessor)processors[0]));
        nbs2.add(((DiffusionCountProcessor)processors[1]));
        nbs2.add(((DiffusionCountProcessor)processors[3]));
        nbs2.add(((DiffusionCountProcessor)processors[4]));
        nbs2.add(((DiffusionCountProcessor)processors[5]));
        nbs2.add(((DiffusionCountProcessor)processors[6]));
        nbs3.add(((DiffusionCountProcessor)processors[0]));
        nbs3.add(((DiffusionCountProcessor)processors[1]));
        nbs3.add(((DiffusionCountProcessor)processors[2]));
        nbs3.add(((DiffusionCountProcessor)processors[4]));
        nbs3.add(((DiffusionCountProcessor)processors[5]));
        nbs3.add(((DiffusionCountProcessor)processors[6]));
        nbs4.add(((DiffusionCountProcessor)processors[0]));
        nbs4.add(((DiffusionCountProcessor)processors[1]));
        nbs4.add(((DiffusionCountProcessor)processors[2]));
        nbs4.add(((DiffusionCountProcessor)processors[3]));
        nbs4.add(((DiffusionCountProcessor)processors[5]));
        nbs4.add(((DiffusionCountProcessor)processors[6]));
        nbs5.add(((DiffusionCountProcessor)processors[0]));
        nbs5.add(((DiffusionCountProcessor)processors[1]));
        nbs5.add(((DiffusionCountProcessor)processors[2]));
        nbs5.add(((DiffusionCountProcessor)processors[3]));
        nbs5.add(((DiffusionCountProcessor)processors[4]));
        nbs5.add(((DiffusionCountProcessor)processors[6]));
        nbs6.add(((DiffusionCountProcessor)processors[0]));
        nbs6.add(((DiffusionCountProcessor)processors[1]));
        nbs6.add(((DiffusionCountProcessor)processors[2]));
        nbs6.add(((DiffusionCountProcessor)processors[3]));
        nbs6.add(((DiffusionCountProcessor)processors[4]));
        nbs6.add(((DiffusionCountProcessor)processors[5]));
        warmup = true;
        processors[0].setNeighbors(nbs0);
        processors[1].setNeighbors(nbs1);
        processors[2].setNeighbors(nbs2);
        processors[3].setNeighbors(nbs3);
        processors[4].setNeighbors(nbs4);
        processors[5].setNeighbors(nbs5);
        processors[6].setNeighbors(nbs6);
        processors[0].setCycleLimit(cycleLimit);
        processors[1].setCycleLimit(cycleLimit);
        processors[2].setCycleLimit(cycleLimit);
        processors[3].setCycleLimit(cycleLimit);
        processors[4].setCycleLimit(cycleLimit);
        processors[5].setCycleLimit(cycleLimit);
        processors[6].setCycleLimit(cycleLimit);
    }
    
    public static void report() {
        op_report_voidTovoid.call(jrvm.getTimestamp());
    }
    private static void report(Op_voidTovoid.JRProxyOp retOp, Cap_voidTovoid fretOp, edu.ucdavis.jr.RemoteHandler handler)
    {
        try    {
            {
                DebugUtil.out("", true);
                JRLoop13: for (int i = 0; i < processors.length; i++) {
                    DebugUtil.out("P(" + DebugUtil.df(i) + ") estimate (" + DebugUtil.df(processors[i].estimate) + ")" + " count (" + DebugUtil.df(processors[i].count) + ") in (" + DebugUtil.df(processors[i].cycle) + ") cycles", true);
                }
                DebugUtil.out("", true);
                double mean = 0;
                JRLoop14: for (int i = 0; i < processors.length; i++) {
                    mean += processors[i].count;
                }
                mean /= processors.length;
                double variance = 0;
                JRLoop15: for (int i = 0; i < processors.length; i++) variance += Math.pow(processors[i].count - mean, 2);
                variance /= processors.length;
                DebugUtil.out(">> MEAN (" + mean + ")" + " VARIANCE (" + variance + ")", true);
                // Return
                { if (retOp != null)
                    retOp.send(jrvm.getTimestamp(), (edu.ucdavis.jr.RemoteHandler) null);
                return ; }
                // End Return

            }
        } catch (Exception JRe)    {
            if (retOp != null && fretOp == null)
            {
        	// if it is a forward cocall with handler
        	if ((handler != null) && !(JRe instanceof java.rmi.RemoteException))
        	    handler.JRhandler(JRe);
        	else
        	    // give preference to propagation through the call stack
        	    retOp.send(jrvm.getTimestamp(), JRe);
            }
            else if ((retOp != null) && (fretOp != null) && !(JRe instanceof java.rmi.RemoteException))
            {
        	// for COSTMT exception handling in operation
        	if (handler != null)
        	    handler.JRhandler(JRe);
        	fretOp.send(jrvm.getTimestamp(), handler);
            }
            else if ((handler != null) && !(JRe instanceof java.rmi.RemoteException))
            {
        	// this should only be for a send/forward
        	handler.JRhandler(JRe);
        	// can rethrow below just to get out of this method
            }
            // rethrow the proper type of exception
            // catch all
            throw new jrRuntimeError("Unhandled exception: " + JRe.toString());
        }
    }
    public static Op_voidTovoid.JRProxyOp JRget_op_report_voidTovoid()
    {
        return op_report_voidTovoid;
    }
    
    public static Op_voidTovoid.JRProxyOp op_report_voidTovoid;
    static class ProcOp_voidTovoid_implreport extends ProcOp_voidTovoid_impl
    {
        public ProcOp_voidTovoid_implreport(PlainDiffusion thisIn) throws RemoteException
        {
        }
        public void call(long JRtimestamp) throws RemoteException
        {
            jrvm.ariseAndReceive();  // from caller
            try    {
                jrvm.setTimestamp(JRtimestamp);
                PlainDiffusion.report(null, null, null);
            } finally {
                jrvm.sendAndDie();    // to caller
            }
        }
        class sendThread implements Runnable
        {
            Op_voidTovoid.JRProxyOp retOp;
            Cap_voidTovoid fretOp;
            edu.ucdavis.jr.RemoteHandler handler;

            public sendThread(Op_voidTovoid.JRProxyOp retOp, edu.ucdavis.jr.RemoteHandler handler)
            {
                this.retOp = retOp;
                this.handler = handler;
            }
            public sendThread(Op_voidTovoid.JRProxyOp retOp, Cap_voidTovoid fretOp,edu.ucdavis.jr.RemoteHandler handler)
            {
                this.retOp = retOp;
                this.fretOp = fretOp;
                this.handler = handler;
            }
            public void run()
            {
                try    {
                    PlainDiffusion.report(this.retOp, this.fretOp, this.handler);
                } catch (Exception e) {/* should be safe to ignore this exception */}
                jrvm.threadDeath();
            }
        }
        public void send(long JRtimestamp) throws RemoteException
        {
            this.send(JRtimestamp, null, null, null);
        }
        public Cap_voidTovoid cosend(long JRtimestamp) throws RemoteException
        {
            return this.cosend(JRtimestamp, null, null, null);
        }
        public void send(long JRtimestamp, edu.ucdavis.jr.RemoteHandler handler) throws RemoteException
        {
            this.send(JRtimestamp, null, handler, null);
        }
        public Cap_voidTovoid cosend(long JRtimestamp, edu.ucdavis.jr.RemoteHandler handler) throws RemoteException
        {
            return this.cosend(JRtimestamp, null, handler, null);
        }
        public void send(long JRtimestamp, Op_voidTovoid.JRProxyOp retOp, edu.ucdavis.jr.RemoteHandler handler, Exception thrown) throws RemoteException
        {
            jrvm.setTimestamp(JRtimestamp);
            jrvm.threadBirth();
            new Thread(new sendThread(retOp, handler)).start();
        }
        public Cap_voidTovoid cosend(long JRtimestamp, Op_voidTovoid.JRProxyOp retOp, edu.ucdavis.jr.RemoteHandler handler, Exception thrown) throws RemoteException
        {
            jrvm.setTimestamp(JRtimestamp);
            jrvm.threadBirth();
            new Thread(new sendThread(null, handler)).start();
            Op_voidTovoid.JRProxyOp myretOp = new Op_voidTovoid.JRProxyOp(new InOp_voidTovoid_impl());
            myretOp.send(jrvm.getTimestamp());
            return new Cap_voidTovoid(myretOp);
        }
        public Cap_voidTovoid cocall(long JRtimestamp) throws RemoteException
        {
            Op_voidTovoid.JRProxyOp retOp = new Op_voidTovoid.JRProxyOp(new InOp_voidTovoid_impl(false));
            jrvm.setTimestamp(JRtimestamp);
            jrvm.threadBirth();
            new Thread(new sendThread(retOp, null)).start();
            Cap_voidTovoid retCap = new Cap_voidTovoid(retOp);
            return retCap;
        }
        public Cap_voidTovoid cocall(long JRtimestamp, edu.ucdavis.jr.RemoteHandler handler, Cap_voidTovoid fretOp) throws RemoteException
        {
            Op_voidTovoid.JRProxyOp retOp = new Op_voidTovoid.JRProxyOp(new InOp_voidTovoid_impl(false));
            jrvm.setTimestamp(JRtimestamp);
            jrvm.threadBirth();
            new Thread(new sendThread(retOp, fretOp, handler)).start();
            Cap_voidTovoid retCap = new Cap_voidTovoid(retOp);
            return retCap;
        }
        public Recv_voidTovoid recv() throws RemoteException
        {
            /* This is an error */
            throw new jrRuntimeError("Receive invoked on an operation/operation capability associated with a method!");
        }
        public void deliverPendingMessages()
        {
            /* This is an error */
            throw new jrRuntimeError("Message delivery invoked on an operation associated with a method!");
        }
        public int length()
        {
            return 0;
        }
        public InOpIterator elements()
        {
            // This is an error
            throw new jrRuntimeError("Elements invoked on an operation / operation capability associated with a method!");
        }
        public InLock getLock()
        {
            // This is an error
            throw new jrRuntimeError("getLock invoked on an operation / operation capability associated with a method!");
        }
        public long getFirstTime()
        {
            // This is an error
            throw new jrRuntimeError("getFirstTime invoked on an operation / operation capability associated with a method!");
        }
        public boolean isRemote(String site)
        {
            // This is an error
            throw new jrRuntimeError("IsRemote invoked on an operation / operation capability associated with a method!");
        }
    }
    ;
    static    {
        try    {
            op_report_voidTovoid = new Op_voidTovoid.JRProxyOp(new ProcOp_voidTovoid_implreport(null));
        } catch (Exception e) { throw new jrRuntimeError(e.toString());}
    }
    
    protected boolean JRcalled = false;
    protected JRPlainDiffusion jrresref;
    public Object JRgetjrresref()
    { try {return jrresref.clone(); } catch (Exception e) {/* not gonna happen */ return null; } }
    protected void JRinit() {
    	if(this.JRcalled) return;
    	jrresref = new JRPlainDiffusion(op_report_voidTovoid);
    	this.JRcalled = true;
    }
    private boolean JRproc = false;
    private void JRprocess() {
    	if (JRproc) return;
    	JRproc = true;
    }
}
